home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / ole2book.zip / CHAP11.ZIP / CHAP11 / COSCHMOO / DOCUMENT.CPP < prev    next >
C/C++ Source or Header  |  1993-06-13  |  21KB  |  966 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Component Schmoo Chapter 11
  4.  *
  5.  * Implementation of the CSchmooDoc derivation of CDocument as
  6.  * well as an implementation of CPolylineAdviseSink.
  7.  *
  8.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Software Design Engineer
  11.  * Microsoft Systems Developer Relations
  12.  *
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #include "coschmoo.h"
  19.  
  20.  
  21.  
  22. /*
  23.  * CSchmooDoc::CSchmooDoc
  24.  * CSchmooDoc::~CSchmooDoc
  25.  *
  26.  * Constructor Parameters:
  27.  *  hInst           HINSTANCE of the application.
  28.  */
  29.  
  30. CSchmooDoc::CSchmooDoc(HINSTANCE hInst)
  31.     : CDocument(hInst)
  32.     {
  33.     m_uPrevSize=SIZE_RESTORED;
  34.     m_pPL=NULL;
  35.     m_pIPersistStorage=NULL;
  36.  
  37.     m_pIAdviseSink=NULL;
  38.     m_dwConn=0;
  39.  
  40.     //CHAPTER8MOD
  41.     m_pDropTarget=NULL;
  42.     m_fDragSource=FALSE;
  43.     //End CHAPTER8MOD
  44.  
  45.     return;
  46.     }
  47.  
  48.  
  49. CSchmooDoc::~CSchmooDoc(void)
  50.     {
  51.     LPDATAOBJECT        pIDataObject;
  52.     HRESULT             hr;
  53.  
  54.     //CHAPTER8MOD
  55.     if (NULL!=m_pDropTarget)
  56.         {
  57.         RevokeDragDrop(m_hWnd);
  58.         CoLockObjectExternal((LPUNKNOWN)m_pDropTarget, FALSE, TRUE);
  59.         m_pDropTarget->Release();
  60.         }
  61.     //End CHAPTER8MOD
  62.  
  63.     //Turn off the advise.
  64.     hr=m_pPL->QueryInterface(IID_IDataObject, (LPVOID FAR *)&pIDataObject);
  65.  
  66.     if (SUCCEEDED(hr))
  67.         pIDataObject->DUnadvise(m_dwConn);
  68.  
  69.     if (NULL!=m_pIAdviseSink)
  70.         delete m_pIAdviseSink;
  71.  
  72.     if (NULL!=m_pIPersistStorage)
  73.         m_pIPersistStorage->Release();
  74.  
  75.     if (NULL!=m_pPLAdv)
  76.         delete m_pPLAdv;
  77.  
  78.     if (NULL!=m_pPL)
  79.         m_pPL->Release();
  80.  
  81.     CoFreeUnusedLibraries();
  82.     return;
  83.     }
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90. /*
  91.  * CSchmooDoc::FInit
  92.  *
  93.  * Purpose:
  94.  *  Initializes an already created document window.  The client actually
  95.  *  creates the window for us, then passes that here for further
  96.  *  initialization.
  97.  *
  98.  * Parameters:
  99.  *  pDI             LPDOCUMENTINIT containing initialization parameters.
  100.  *
  101.  * Return Value:
  102.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  103.  */
  104.  
  105. BOOL CSchmooDoc::FInit(LPDOCUMENTINIT pDI)
  106.     {
  107.     RECT            rc;
  108.     HRESULT         hr;
  109.     FORMATETC       fe;
  110.     LPDATAOBJECT    pIDataObject;
  111.  
  112.     //Change the stringtable range to our customization.
  113.     pDI->idsMin=IDS_DOCUMENTMIN;
  114.     pDI->idsMax=IDS_DOCUMENTMAX;
  115.  
  116.     //Do default initialization
  117.     if (!CDocument::FInit(pDI))
  118.         return FALSE;
  119.  
  120.     //CHAPTER11MOD
  121.     //Create the Polyline Object via COMPOBJ.DLL functions.
  122.     hr=CoCreateInstance(CLSID_Polyline11, NULL, CLSCTX_INPROC_SERVER
  123.         , IID_IPolyline6, (LPVOID FAR *)&m_pPL);
  124.     //End CHAPTER11MOD
  125.  
  126.     if (FAILED(hr))
  127.         return FALSE;
  128.  
  129.     //Initialize the contained Polyline which creates a window.
  130.     GetClientRect(m_hWnd, &rc);
  131.     InflateRect(&rc, -8, -8);
  132.  
  133.     if (FAILED(m_pPL->Init(m_hWnd, &rc, WS_CHILD | WS_VISIBLE, ID_POLYLINE)))
  134.         return FALSE;
  135.  
  136.  
  137.     //Set up an advise on the Polyline.
  138.     m_pPLAdv=new CPolylineAdviseSink((LPVOID)this, (LPUNKNOWN)this);
  139.  
  140.     if (NULL==m_pPLAdv)
  141.         return FALSE;
  142.  
  143.     m_pPL->SetAdvise(m_pPLAdv);
  144.  
  145.     //Get the IPersistStorage interface on the object for loads & saves.
  146.     hr=m_pPL->QueryInterface(IID_IPersistStorage, (LPVOID FAR *)&m_pIPersistStorage);
  147.  
  148.     if (FAILED(hr))
  149.         return FALSE;
  150.  
  151.     /*
  152.      * Create an IAdviseSink and send it to the Polyline's IDataObject
  153.      * with the clipboard format for the Polyline (as in IPOLY6.H).
  154.      */
  155.  
  156.     //This is a private macro.
  157.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  158.  
  159.     m_pIAdviseSink=new CImpIAdviseSink((LPVOID)this, (LPUNKNOWN)this);
  160.  
  161.     if (NULL==m_pIAdviseSink)
  162.         return FALSE;
  163.  
  164.     //Set up an advise for the Polyline format
  165.     hr=m_pPL->QueryInterface(IID_IDataObject, (LPVOID FAR *)&pIDataObject);
  166.  
  167.     if (FAILED(hr))
  168.         return FALSE;
  169.  
  170.     pIDataObject->DAdvise(&fe, ADVF_NODATA, m_pIAdviseSink, &m_dwConn);
  171.     pIDataObject->Release();
  172.  
  173.  
  174.     //CHAPTER8MOD
  175.     m_pDropTarget=new CDropTarget(this);
  176.  
  177.     if (NULL!=m_pDropTarget)
  178.         {
  179.         m_pDropTarget->AddRef();
  180.         RegisterDragDrop(m_hWnd, (LPDROPTARGET)m_pDropTarget);
  181.         CoLockObjectExternal((LPUNKNOWN)m_pDropTarget, TRUE, FALSE);
  182.         }
  183.     //End CHAPTER8MOD
  184.  
  185.     return TRUE;
  186.     }
  187.  
  188.  
  189.  
  190.  
  191. //IUnknown interface for all the interfaces we implement in the document
  192.  
  193. /*
  194.  * CSchmooDoc::QueryInterface
  195.  * CSchmooDoc::AddRef
  196.  * CSchmooDoc::Release
  197.  *
  198.  * Purpose:
  199.  *  IUnknown members for the CSchmooDoc implementation.
  200.  */
  201.  
  202. STDMETHODIMP CSchmooDoc::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  203.     {
  204.     *ppv=NULL;
  205.  
  206.     //The document is the unknown
  207.     if (IsEqualIID(riid, IID_IUnknown))
  208.         *ppv=(LPVOID)this;
  209.  
  210.     //Return contained interfaces for others.
  211.     if (IsEqualIID(riid, IID_IPolylineAdviseSink6))
  212.         *ppv=(LPVOID)m_pPLAdv;
  213.  
  214.     if (IsEqualIID(riid, IID_IAdviseSink))
  215.         *ppv=(LPVOID)m_pIAdviseSink;
  216.  
  217.     /*
  218.      * If we actually assign an interface to ppv we need to AddRef it
  219.      * since we're returning a new pointer.
  220.      */
  221.     if (NULL!=*ppv)
  222.         {
  223.         ((LPUNKNOWN)*ppv)->AddRef();
  224.         return NOERROR;
  225.         }
  226.  
  227.     return ResultFromScode(S_FALSE);
  228.     }
  229.  
  230.  
  231. STDMETHODIMP_(ULONG) CSchmooDoc::AddRef(void)
  232.     {
  233.     return ++m_cRef;
  234.     }
  235.  
  236.  
  237. STDMETHODIMP_(ULONG) CSchmooDoc::Release(void)
  238.     {
  239.     /*
  240.      * Since CoSchmoo doesn't use documents like Component Objects, this
  241.      * doesn't do anything except provide a debugging point.
  242.      */
  243.     return --m_cRef;
  244.     }
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253. /*
  254.  * CSchmooDoc::FMessageHook
  255.  *
  256.  * Purpose:
  257.  *  Processes WM_SIZE for the document so we can resize the Polyline.
  258.  *
  259.  * Parameters:
  260.  *  <WndProc Parameters>
  261.  *  pLRes           LRESULT FAR * in which to store the return value
  262.  *                  for the message.
  263.  *
  264.  * Return Value:
  265.  *  BOOL            TRUE to prevent further processing, FALSE otherwise.
  266.  */
  267.  
  268. BOOL CSchmooDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  269.     , LPARAM lParam, LRESULT FAR *pLRes)
  270.     {
  271.     UINT        dx, dy;
  272.     RECT        rc;
  273.  
  274.     if (WM_SIZE==iMsg)
  275.         {
  276.         //Don't effect the Polyline size to or from minimized state.
  277.         if (SIZE_MINIMIZED!=wParam && SIZE_MINIMIZED !=m_uPrevSize)
  278.             {
  279.             //When we change size, resize any Polyline we hold.
  280.             dx=LOWORD(lParam);
  281.             dy=HIWORD(lParam);
  282.  
  283.             /*
  284.              * If we are getting WM_SIZE in response to a Polyline
  285.              * notification, then don't resize the Polyline window again.
  286.              */
  287.             if (!m_fNoSize && NULL!=m_pPL)
  288.                 {
  289.                 //Resize the polyline to fit the new client
  290.                 SetRect(&rc, 8, 8, dx-8, dy-8);
  291.                 m_pPL->RectSet(&rc, FALSE);
  292.  
  293.                 /*
  294.                  * We consider sizing something that makes the file dirty,
  295.                  * but not until we've finished the create process, which
  296.                  * is why we set fNoDirty to FALSE in WM_CREATE since we
  297.                  * get a WM_SIZE on the first creation.
  298.                  */
  299.                 if (!m_fNoDirty)
  300.                     FDirtySet(TRUE);
  301.  
  302.                 SetRect(&rc, 0, 0, dx, dy);
  303.  
  304.                 if (NULL!=m_pAdv)
  305.                     m_pAdv->OnSizeChange((LPCDocument)this, &rc);
  306.  
  307.                 m_fNoDirty=FALSE;
  308.                 }
  309.             }
  310.  
  311.         m_uPrevSize=wParam;
  312.         }
  313.  
  314.     //CHAPTER8MOD
  315.     if (WM_LBUTTONDOWN==iMsg)
  316.             {
  317.             LPDROPSOURCE    pIDropSource;
  318.             LPDATAOBJECT    pIDataObject;
  319.             HRESULT         hr;
  320.             SCODE           sc;
  321.             DWORD           dwEffect;
  322.  
  323.             pIDropSource=(LPDROPSOURCE)new CDropSource(this);
  324.  
  325.             if (NULL==pIDropSource)
  326.                 return FALSE;
  327.  
  328.             pIDropSource->AddRef();
  329.             m_fDragSource=TRUE;
  330.  
  331.             //Go get the data and start the ball rolling.
  332.             pIDataObject=TransferObjectCreate();
  333.  
  334.             hr=DoDragDrop(pIDataObject, pIDropSource
  335.                 , DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);
  336.  
  337.             pIDataObject->Release();
  338.             pIDropSource->Release();
  339.  
  340.             m_fDragSource=FALSE;
  341.  
  342.             sc=GetScode(hr);
  343.  
  344.             if (DRAGDROP_S_DROP==sc && DROPEFFECT_MOVE==dwEffect)
  345.                 {
  346.                 m_pPL->New();
  347.                 FDirtySet(TRUE);
  348.                 }
  349.  
  350.             return TRUE;
  351.             }
  352.        //End CHAPTER8MOD
  353.  
  354.  
  355.     /*
  356.      * We return FALSE even on WM_SIZE so we can let the default procedure
  357.      * handle maximized MDI child windows appropriately.
  358.      */
  359.     return FALSE;
  360.     }
  361.  
  362.  
  363.  
  364.  
  365.  
  366.  
  367.  
  368.  
  369. /*
  370.  * CSchmooDoc::Clear
  371.  *
  372.  * Purpose:
  373.  *  Sets all contents in the document back to defaults with no filename.
  374.  *
  375.  * Paramters:
  376.  *  None
  377.  *
  378.  * Return Value:
  379.  *  None
  380.  */
  381.  
  382. void CSchmooDoc::Clear(void)
  383.     {
  384.     //Completely reset the polyline
  385.     m_pPL->New();
  386.  
  387.     CDocument::Clear();
  388.     return;
  389.     }
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396. /*
  397.  * CSchmooDoc::ULoad
  398.  *
  399.  * Purpose:
  400.  *  Loads a given document without any user interface overwriting the
  401.  *  previous contents of the Polyline window.  We do this by opening
  402.  *  the file and telling the Polyline to load itself from that file.
  403.  *
  404.  * Parameters:
  405.  *  fChangeFile     BOOL indicating if we're to update the window title
  406.  *                  and the filename from using this file.
  407.  *  pszFile         LPSTR to the filename to load, NULL for untitled.
  408.  *
  409.  * Return Value:
  410.  *  UINT            An error value from DOCERR_*
  411.  */
  412.  
  413. UINT CSchmooDoc::ULoad(BOOL fChangeFile, LPSTR pszFile)
  414.     {
  415.     HRESULT             hr;
  416.     LPSTORAGE           pIStorage;
  417.  
  418.     if (NULL==pszFile)
  419.         {
  420.         /*
  421.          * As a user of an IPersistStorage we have to provide all objects
  422.          * with an IStorage they can use for incremental access passing
  423.          * that storage to ::InitNew.  Here we create a temporary file
  424.          * that we don't bother holding on to.  If the object doesn't
  425.          * use it, then our ::Release destroys it immediately.
  426.          */
  427.  
  428.         hr=StgCreateDocfile(NULL, STGM_DIRECT | STGM_READWRITE | STGM_CREATE
  429.             | STGM_DELETEONRELEASE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  430.  
  431.         if (FAILED(hr))
  432.             return DOCERR_COULDNOTOPEN;
  433.  
  434.         m_pIPersistStorage->InitNew(pIStorage);
  435.         pIStorage->Release();
  436.  
  437.         Rename(NULL);
  438.         return DOCERR_NONE;
  439.         }
  440.  
  441.     /*
  442.      * Open a storage and pass it to the Polyline via IPersistStorage.
  443.      * We do not remain compatible with previous files saved with
  444.      * Component Schmoo.
  445.      */
  446.  
  447.     hr=StgOpenStorage(pszFile, NULL, STGM_DIRECT | STGM_READ
  448.         | STGM_SHARE_EXCLUSIVE, NULL, 0, &pIStorage);
  449.  
  450.     if (FAILED(hr))
  451.         return DOCERR_COULDNOTOPEN;
  452.  
  453.     hr=m_pIPersistStorage->Load(pIStorage);
  454.  
  455.     pIStorage->Release();
  456.  
  457.     if (FAILED(hr))
  458.         return DOCERR_READFAILURE;
  459.  
  460.     if (fChangeFile)
  461.         Rename(pszFile);
  462.  
  463.     //Importing a file makes things dirty
  464.     FDirtySet(!fChangeFile);
  465.  
  466.     return DOCERR_NONE;
  467.     }
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475. /*
  476.  * CSchmooDoc::USave
  477.  *
  478.  * Purpose:
  479.  *  Writes the file to a known filename, requiring that the user has
  480.  *  previously used FileOpen or FileSaveAs in order to have a filename.
  481.  *
  482.  * Parameters:
  483.  *  uType           UINT indicating the type of file the user requested
  484.  *                  to save in the File Save As dialog.
  485.  *  pszFile         LPSTR under which to save.  If NULL, use the current name.
  486.  *
  487.  * Return Value:
  488.  *  UINT            An error value from DOCERR_*
  489.  */
  490.  
  491. UINT CSchmooDoc::USave(UINT uType, LPSTR pszFile)
  492.     {
  493.     BOOL                fRename=TRUE;
  494.     HRESULT             hr;
  495.     LPSTORAGE           pIStorage;
  496.  
  497.     if (NULL==pszFile)
  498.         {
  499.         fRename=FALSE;
  500.         pszFile=m_szFile;
  501.         }
  502.  
  503.     /*
  504.      * In Component Schmoo, we only deal with one version of data,
  505.      * so all the code in Chapter 2 Schmoo that dealt with 1.0 and
  506.      * 2.0 files has been removed.
  507.      */
  508.  
  509.     hr=StgCreateDocfile(pszFile, STGM_DIRECT | STGM_READWRITE
  510.         | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  511.  
  512.     if (FAILED(hr))
  513.         return DOCERR_COULDNOTOPEN;
  514.  
  515.     //Tell the object to save, and also tell it that we're done.
  516.     m_pIPersistStorage->Save(pIStorage, FALSE);
  517.     m_pIPersistStorage->SaveCompleted(pIStorage);
  518.  
  519.     pIStorage->Release();
  520.  
  521.     if (FAILED(hr))
  522.         return DOCERR_WRITEFAILURE;
  523.  
  524.     //Saving makes us clean
  525.     FDirtySet(FALSE);
  526.  
  527.     if (fRename)
  528.         Rename(pszFile);
  529.  
  530.     return DOCERR_NONE;
  531.     }
  532.  
  533.  
  534.  
  535. /*
  536.  * CSchmooDoc::Undo
  537.  *
  538.  * Purpose:
  539.  *  Reverses a previous action.
  540.  *
  541.  * Parameters:
  542.  *  None
  543.  *
  544.  * Return Value:
  545.  *  None
  546.  */
  547.  
  548. void CSchmooDoc::Undo(void)
  549.     {
  550.     m_pPL->Undo();
  551.     return;
  552.     }
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559. /*
  560.  * CSchmooDoc::FClip
  561.  *
  562.  * Purpose:
  563.  *  Places a private format, a metafile, and a bitmap of the display
  564.  *  on the clipboard, optionally implementing Cut by deleting the
  565.  *  data in the current window after rendering.
  566.  *
  567.  * Parameters:
  568.  *  hWndFrame       HWND of the main window.
  569.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  570.  *
  571.  * Return Value:
  572.  *  BOOL            TRUE if successful, FALSE otherwise.
  573.  */
  574.  
  575. BOOL CSchmooDoc::FClip(HWND hWndFrame, BOOL fCut)
  576.     {
  577.     BOOL            fRet=TRUE;
  578.     LPDATAOBJECT    pIDataObject;
  579.  
  580.     //CHAPTER8MOD
  581.     pIDataObject=TransferObjectCreate();
  582.  
  583.     if (NULL==pIDataObject)
  584.         return FALSE;
  585.     //CHAPTER8MOD
  586.  
  587.  
  588.     fRet=SUCCEEDED(OleSetClipboard(pIDataObject));
  589.     pIDataObject->Release();
  590.  
  591.     //Delete our current data if copying succeeded.
  592.     if (fRet && fCut)
  593.         {
  594.         m_pPL->New();
  595.         FDirtySet(TRUE);
  596.         }
  597.  
  598.  
  599.     return fRet;
  600.     }
  601.  
  602.  
  603.  
  604.  
  605.  
  606. /*
  607.  * CSchmooDoc::FQueryPaste
  608.  *
  609.  * Purpose:
  610.  *  Determines if we can paste data from the clipboard.
  611.  *
  612.  * Parameters:
  613.  *  None
  614.  *
  615.  * Return Value:
  616.  *  BOOL            TRUE if data is available, FALSE otherwise.
  617.  */
  618.  
  619. BOOL CSchmooDoc::FQueryPaste(void)
  620.     {
  621.     LPDATAOBJECT    pIDataObject;
  622.     BOOL            fRet;
  623.  
  624.     if (FAILED(OleGetClipboard(&pIDataObject)))
  625.         return FALSE;
  626.  
  627.     //CHAPTER8MOD
  628.     fRet=FQueryPasteFromData(pIDataObject);
  629.     //End CHAPTER8MOD
  630.  
  631.     pIDataObject->Release();
  632.     return fRet;
  633.     }
  634.  
  635.  
  636.  
  637. //CHAPTER8MOD
  638. /*
  639.  * CSchmooDoc::FQueryPasteFromData
  640.  * (Protected)
  641.  *
  642.  * Purpose:
  643.  *  Determines if we can paste data from a data object.
  644.  *
  645.  * Parameters:
  646.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  647.  *
  648.  * Return Value:
  649.  *  BOOL            TRUE if data is available, FALSE otherwise.
  650.  */
  651.  
  652. BOOL CSchmooDoc::FQueryPasteFromData(LPDATAOBJECT pIDataObject)
  653.     {
  654.     FORMATETC       fe;
  655.  
  656.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  657.     return (NOERROR==pIDataObject->QueryGetData(&fe));
  658.     }
  659. //End CHAPTER8MOD
  660.  
  661.  
  662.  
  663.  
  664.  
  665. /*
  666.  * CSchmooDoc::FPaste
  667.  *
  668.  * Purpose:
  669.  *  Retrieves the private data format from the clipboard and sets it
  670.  *  to the current figure in the editor window.
  671.  *
  672.  *  Note that if this function is called, then the clipboard format
  673.  *  is available because the Paste menu item is only enabled if the
  674.  *  format is present.
  675.  *
  676.  * Parameters:
  677.  *  hWndFrame       HWND of the main window.
  678.  *
  679.  * Return Value:
  680.  *  BOOL            TRUE if successful, FALSE otherwise.
  681.  */
  682.  
  683. BOOL CSchmooDoc::FPaste(HWND hWndFrame)
  684.     {
  685.     LPDATAOBJECT    pIDataObject;
  686.     BOOL            fRet;
  687.  
  688.     if (FAILED(OleGetClipboard(&pIDataObject)))
  689.         return FALSE;
  690.  
  691.     //CHAPTER8MOD
  692.     fRet=FPasteFromData(pIDataObject);
  693.     //End CHAPTER8MOD
  694.  
  695.     pIDataObject->Release();
  696.     return TRUE;
  697.     }
  698.  
  699.  
  700.  
  701. //CHAPTER8MOD
  702.  
  703.  
  704. /*
  705.  * CSchmooDoc::FPasteFromData
  706.  * (Protected)
  707.  *
  708.  * Purpose:
  709.  *  Retrieves the private data format from a data object and sets it
  710.  *  to the current figure in the editor window.
  711.  *
  712.  * Parameters:
  713.  *  pIDataObject    LPDATAOBJECT from which to paste.
  714.  *
  715.  * Return Value:
  716.  *  BOOL            TRUE if successful, FALSE otherwise.
  717.  */
  718.  
  719. BOOL CSchmooDoc::FPasteFromData(LPDATAOBJECT pIDataObject)
  720.     {
  721.     FORMATETC       fe;
  722.     STGMEDIUM       stm;
  723.     BOOL            fRet;
  724.  
  725.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  726.     fRet=SUCCEEDED(pIDataObject->GetData(&fe, &stm));
  727.  
  728.     if (!fRet || NULL==stm.hGlobal)
  729.         return FALSE;
  730.  
  731.     if (fRet && NULL!=stm.hGlobal)
  732.         {
  733.         m_pPL->QueryInterface(IID_IDataObject, (LPVOID FAR *)&pIDataObject);
  734.         pIDataObject->SetData(&fe, &stm, TRUE);
  735.         pIDataObject->Release();
  736.  
  737.         FDirtySet(TRUE);
  738.         }
  739.  
  740.     return fRet;
  741.     }
  742.  
  743.  
  744.  
  745.  
  746. /*
  747.  * CSchmooDoc::TransferObjectCreate
  748.  * (Protected)
  749.  *
  750.  * Purpose:
  751.  *  Creates a DataTransferObject and stuffs the current Polyline
  752.  *  data into it, used for both clipboard and drag-drop operations.
  753.  *
  754.  * Parameters:
  755.  *  None
  756.  *
  757.  * Return Value:
  758.  *  LPDATAOBJECT    Pointer to the object created, NULL on failure
  759.  */
  760.  
  761. LPDATAOBJECT CSchmooDoc::TransferObjectCreate(void)
  762.     {
  763.     UINT            i;
  764.     HRESULT         hr;
  765.     STGMEDIUM       stm;
  766.     FORMATETC       fe;
  767.     LPDATAOBJECT    pIDataSrc;
  768.     LPDATAOBJECT    pIDataObject=NULL;
  769.     const UINT      cFormats=3;
  770.     static UINT     rgcf[3]={0, CF_METAFILEPICT, CF_BITMAP};
  771.     static DWORD    rgtm[3]={TYMED_HGLOBAL, TYMED_MFPICT, TYMED_GDI};
  772.  
  773.     hr=CoCreateInstance(CLSID_DataTransferObject, NULL, CLSCTX_INPROC_SERVER
  774.         , IID_IDataObject, (LPVOID FAR *)&pIDataObject);
  775.  
  776.     if (FAILED(hr))
  777.         return NULL;
  778.  
  779.     rgcf[0]=m_cf;
  780.  
  781.     hr=m_pPL->QueryInterface(IID_IDataObject, (LPVOID FAR *)&pIDataSrc);
  782.  
  783.     if (FAILED(hr))
  784.         {
  785.         pIDataObject->Release();
  786.         return NULL;
  787.         }
  788.  
  789.     for (i=0; i < cFormats; i++)
  790.         {
  791.         //Copy private data first.
  792.         SETDefFormatEtc(fe, rgcf[i], rgtm[i]);
  793.  
  794.         if (SUCCEEDED(pIDataSrc->GetData(&fe, &stm)))
  795.             pIDataObject->SetData(&fe, &stm, TRUE);
  796.         }
  797.  
  798.     pIDataSrc->Release();
  799.     return pIDataObject;    //Caller now responsible
  800.     }
  801.  
  802.  
  803.  
  804.  
  805.  
  806. /*
  807.  * CSchmooDoc::DropSelectTargetWindow
  808.  * (Protected)
  809.  *
  810.  * Purpose:
  811.  *  Creates a thin inverted frame around a window that we use to show
  812.  *  the window as a drop target.  This is a toggle function:  it uses
  813.  *  XOR to create the effect so it must be called twice to leave the
  814.  *  window as it was.
  815.  *
  816.  * Parameters:
  817.  *  None
  818.  *
  819.  * Return Value:
  820.  *  None
  821.  */
  822.  
  823. void CSchmooDoc::DropSelectTargetWindow(void)
  824.     {
  825.     HDC         hDC;
  826.     RECT        rc;
  827.     UINT        dd=3;
  828.     HWND        hWnd;
  829.  
  830.     m_pPL->Window(&hWnd);
  831.     hDC=GetWindowDC(hWnd);
  832.     GetClientRect(hWnd, &rc);
  833.  
  834.     //Frame this window with inverted pixels
  835.  
  836.     //Top
  837.     PatBlt(hDC, rc.left, rc.top, rc.right-rc.left, dd, DSTINVERT);
  838.  
  839.     //Bottom
  840.     PatBlt(hDC, rc.left, rc.bottom-dd, rc.right-rc.left, dd, DSTINVERT);
  841.  
  842.     //Left excluding regions already affected by top and bottom
  843.     PatBlt(hDC, rc.left, rc.top+dd, dd, rc.bottom-rc.top-(2*dd), DSTINVERT);
  844.  
  845.     //Right excluding regions already affected by top and bottom
  846.     PatBlt(hDC, rc.right-dd, rc.top+dd, dd, rc.bottom-rc.top-(2*dd), DSTINVERT);
  847.  
  848.     ReleaseDC(hWnd, hDC);
  849.     return;
  850.     }
  851.  
  852. //End CHAPTER8MOD
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861. /*
  862.  * CSchmooDoc::ColorSet
  863.  *
  864.  * Purpose:
  865.  *  Changes a color used in our contained Polyline.
  866.  *
  867.  * Parameters:
  868.  *  iColor          UINT index of the color to change.
  869.  *  cr              COLORREF new color.
  870.  *
  871.  * Return Value:
  872.  *  COLORREF        Previous color for the given index.
  873.  */
  874.  
  875. COLORREF CSchmooDoc::ColorSet(UINT iColor, COLORREF cr)
  876.     {
  877.     COLORREF    crRet;
  878.  
  879.     m_pPL->ColorSet(iColor, cr, &crRet);
  880.     return crRet;
  881.     }
  882.  
  883.  
  884.  
  885.  
  886.  
  887. /*
  888.  * CSchmooDoc::ColorGet
  889.  *
  890.  * Purpose:
  891.  *  Retrieves a color currently in use in the Polyline.
  892.  *
  893.  * Parameters:
  894.  *  iColor          UINT index of the color to retrieve.
  895.  *
  896.  * Return Value:
  897.  *  COLORREF        Current color for the given index.
  898.  */
  899.  
  900. COLORREF CSchmooDoc::ColorGet(UINT iColor)
  901.     {
  902.     COLORREF    crRet;
  903.  
  904.     m_pPL->ColorGet(iColor, &crRet);
  905.     return crRet;
  906.     }
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913. /*
  914.  * CSchmooDoc::LineStyleSet
  915.  *
  916.  * Purpose:
  917.  *  Changes the line style currently used in the Polyline
  918.  *
  919.  * Parameters:
  920.  *  iStyle          UINT index of the new line style to use.
  921.  *
  922.  * Return Value:
  923.  *  UINT            Previous line style.
  924.  */
  925.  
  926.  
  927. UINT CSchmooDoc::LineStyleSet(UINT iStyle)
  928.     {
  929.     UINT    i;
  930.  
  931.     m_pPL->LineStyleSet(iStyle, &i);
  932.     return i;
  933.     }
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941. /*
  942.  * CSchmooDoc::LineStyleGet
  943.  *
  944.  * Purpose:
  945.  *  Retrieves the line style currently used in the Polyline
  946.  *
  947.  * Parameters:
  948.  *  None
  949.  *
  950.  * Return Value:
  951.  *  UINT            Current line style.
  952.  */
  953.  
  954.  
  955. UINT CSchmooDoc::LineStyleGet(void)
  956.     {
  957.     UINT    i;
  958.  
  959.     m_pPL->LineStyleGet(&i);
  960.     return i;
  961.     }
  962.  
  963.  
  964.  
  965. //CPolylineAdviseSink moved to IADVSINK.CPP
  966.